<template>
  <view class="selector-container">
    <view class="selector-input" @click="toggleSelector">
      <text class="selector-placeholder" v-if="!selectedItem">{{ placeholder }}</text>
      <text class="selector-value" v-else>{{ getDisplayText(selectedItem) }}</text>
      <text class="selector-arrow" :class="{ 'is-open': isOpen }">&#xe65e;</text>
    </view>
    
    <view v-if="isOpen" class="selector-dropdown-mask" @click="closeSelector">
      <view class="selector-dropdown" @click.stop>
        <view class="dropdown-header">
          <text class="cancel-btn" @click="closeSelector">取消</text>
          <text class="title">{{ title }}</text>
          <text class="confirm-btn" @click="confirmSelection">确定</text>
        </view>
        <scroll-view class="dropdown-content" scroll-y>
          <view 
            v-for="(item, index) in options" 
            :key="index" 
            class="dropdown-item"
            :class="{ 'is-active': isItemSelected(item) }"
            @click="selectItem(item)"
          >
            <slot name="item" :item="item">
              {{ getDisplayText(item) }}
            </slot>
          </view>
          <view v-if="options.length === 0" class="empty-tip">
            {{ emptyTip }}
          </view>
        </scroll-view>
      </view>
    </view>
  </view>
</template>

<script lang="ts">
import { defineComponent, ref, computed, PropType } from 'vue';

export default defineComponent({
  name: 'Selector',
  props: {
    options: {
      type: Array as PropType<any[]>,
      default: () => []
    },
    value: {
      type: [Object, String, Number],
      default: null
    },
    placeholder: {
      type: String,
      default: '请选择'
    },
    title: {
      type: String,
      default: '请选择'
    },
    emptyTip: {
      type: String,
      default: '暂无数据'
    },
    labelKey: {
      type: String,
      default: 'label'
    },
    valueKey: {
      type: String,
      default: 'value'
    },
    displayFormat: {
      type: Function as PropType<(item: any) => string>,
      default: null
    }
  },
  emits: ['update:value', 'change'],
  setup(props, { emit }) {
    const isOpen = ref(false);
    const selectedItem = ref(props.value);
    const tempSelectedItem = ref(props.value);
    
    // 切换选择器显示状态
    const toggleSelector = () => {
      isOpen.value = !isOpen.value;
      if (isOpen.value) {
        tempSelectedItem.value = selectedItem.value;
      }
    };
    
    // 关闭选择器
    const closeSelector = () => {
      isOpen.value = false;
    };
    
    // 获取显示文本
    const getDisplayText = (item: any): string => {
      if (!item) return '';
      
      if (props.displayFormat) {
        return props.displayFormat(item);
      }
      
      if (typeof item === 'object') {
        return item[props.labelKey] || '';
      }
      
      return String(item);
    };
    
    // 判断项目是否被选中
    const isItemSelected = (item: any): boolean => {
      if (!tempSelectedItem.value || !item) return false;
      
      if (typeof item === 'object' && typeof tempSelectedItem.value === 'object') {
        return item[props.valueKey] === tempSelectedItem.value[props.valueKey];
      }
      
      return item === tempSelectedItem.value;
    };
    
    // 选择项目
    const selectItem = (item: any) => {
      tempSelectedItem.value = item;
    };
    
    // 确认选择
    const confirmSelection = () => {
      selectedItem.value = tempSelectedItem.value;
      emit('update:value', selectedItem.value);
      emit('change', selectedItem.value);
      closeSelector();
    };
    
    return {
      isOpen,
      selectedItem,
      toggleSelector,
      closeSelector,
      getDisplayText,
      isItemSelected,
      selectItem,
      confirmSelection
    };
  }
});
</script>

<style lang="scss">
.selector-container {
  width: 100%;
  position: relative;
}

.selector-input {
  width: 100%;
  height: 80rpx;
  border-bottom: 1px solid #f0f0f0;
  padding: 0 20rpx;
  display: flex;
  justify-content: space-between;
  align-items: center;
  box-sizing: border-box;
}

.selector-placeholder {
  font-size: 32rpx;
  color: #999;
}

.selector-value {
  font-size: 32rpx;
  color: #333;
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.selector-arrow {
  font-family: "iconfont";
  color: #999;
  transition: transform 0.3s;
  
  &.is-open {
    transform: rotate(180deg);
  }
}

.selector-dropdown-mask {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  z-index: 999;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}

.selector-dropdown {
  background-color: #fff;
  border-top-left-radius: 20rpx;
  border-top-right-radius: 20rpx;
  max-height: 70vh;
  display: flex;
  flex-direction: column;
}

.dropdown-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 25rpx 30rpx;
  border-bottom: 1px solid #f0f0f0;
}

.cancel-btn {
  color: #999;
  font-size: 28rpx;
}

.title {
  color: #333;
  font-size: 30rpx;
  font-weight: 500;
}

.confirm-btn {
  color: #a8c6df;
  font-size: 28rpx;
}

.dropdown-content {
  max-height: 60vh;
}

.dropdown-item {
  padding: 30rpx;
  border-bottom: 1px solid #f5f5f5;
  font-size: 30rpx;
  color: #333;
  
  &.is-active {
    background-color: #f8f8f8;
    color: #a8c6df;
  }
}

.empty-tip {
  padding: 60rpx 0;
  text-align: center;
  font-size: 28rpx;
  color: #999;
}
</style>
